////////////////////////////////////////////////
//	File:		Game.cpp
//	Class:		SGP
//	Updated:	3/8/2012
//	Author:		Roc Myers
//	Purpose:	To contain all game related code
////////////////////////////////////////////////

#include "Game.h"
#include "ZoidbergState.h"
#include "tinyxml/tinyxml.h"
#include "AnimationManager.h"

Game* Game::pInstance = nullptr;

// Default Constructor
Game::Game(void)
{
	D3D	= nullptr;
	TM	= nullptr;
	DI	= nullptr;
	XA	= nullptr;
	CurState = nullptr;
	Manager = nullptr;

	Width	 = 0;
	Height	 = 0;
	Windowed = false;
	InFocus	 = true;

	SfxVol		= 0.0f;
	BgmVol		= 0.0f;
	Pan			= 0.0f;
	Fullscreen = false;
	MusicVol = 0.0f;

	ActiveFile = -1;
	CurMap = -1;
	drinkID = -1;
	blankRectBmpID = -1;
}	

// Destructor
Game::~Game(void)
{
}

// PROPER SINGLETON accessor
Game* Game::GetInstance(void)
{
	if(pInstance == nullptr)
		pInstance = new Game();
	else
		return pInstance;

	return pInstance;
}

// PROPER SINGLETON deletion
void Game::DeleteInstance()
{
	if(pInstance != nullptr)
	{
		delete pInstance;
		pInstance = nullptr;
	}
}

// Initialize
void Game::Initialize(HWND hWnd, HINSTANCE hInstance, int nScreenWidth, int nScreenHeight, bool bIsWindowed)
{
	// Acquire and initialize SGD Wrappers
	D3D	= CSGD_Direct3D::GetInstance();
	TM	= CSGD_TextureManager::GetInstance();
	DI	= CSGD_DirectInput::GetInstance();
	XA	= CSGD_XAudio2::GetInstance();

	D3D->InitDirect3D(hWnd, nScreenWidth, nScreenHeight, bIsWindowed, false);
	TM->InitTextureManager(D3D->GetDirect3DDevice(), D3D->GetSprite());
	DI->InitDirectInput(hWnd, hInstance, DI_KEYBOARD | DI_MOUSE | DI_JOYSTICKS);

	XA->InitXAudio2();
	
	// If there isn't a settings file, use the XAudio2 defaults
	if(!LoadSettings("settings.xml"))
	{
		SfxVol	= CSGD_XAudio2::GetInstance()->SFXGetMasterVolume();
		BgmVol	= CSGD_XAudio2::GetInstance()->MusicGetMasterVolume();
	}

	// Set screen parameters
	Width	= nScreenWidth;
	Height	= nScreenHeight;
	Windowed = bIsWindowed;

	drinkID		= CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("resource/soundFX/FX/DrinkSoda.wav"));

	// Get Animation Manager
	Manager = AnimationManager::GetInstance();

	// Enter Splash Screen
	ChangeState(ZoidbergState::GetInstance());

	blankRectBmpID = TM->LoadTexture(_T("resource/blankRect.png"),D3DCOLOR_XRGB(0,0,0));

}

// Execute
bool Game::Main(void)
{
	if(InFocus)
	{
		if(XA->MusicGetMasterVolume() == 0)
			XA->MusicSetMasterVolume(MusicVol);

		if(Input() == false)
			return false;

		// Calculate the elapsed time
		DWORD now = GetTickCount();
		float elapsedTime = (now - Time) / 1000.0f;
		Time = now;

		// Cap the elapsed time at 1/8 second
		if( elapsedTime > 0.125f )
			elapsedTime = 0.125f;

		Update(elapsedTime);
	}
	else
	{
		if(XA->MusicGetMasterVolume() != 0)
			MusicVol = XA->MusicGetMasterVolume();

		XA->MusicSetMasterVolume(0);
	}

	Render();

	return true;
}

// Handle Input
bool Game::Input(void)
{
	// Refresh the Direct Input wrapper (ONLY ONCE PER FRAME OR ELSE)
	DI->ReadDevices();

	// Current State Input
	cout << "Game.cpp CurStateInput: 150";
	if(CurState)
		CurState->Input();
	else
	{
		return false;
	}
	// Keep running the game
	return true;
}

// Update
void Game::Update(float fElapsedTime)
{
	
	// Update XAudio2
	XA->Update();

	// Update Current State
	cout << "Game.cpp CurStateUpdate: 169";
	if(CurState)
		CurState->Update(fElapsedTime);
	
}

// Render Current Game State
void Game::Render(void)
{
	// Clear the backbuffer
	D3D->Clear(0,0,0);

	// Start D3D Rendering
	D3D->DeviceBegin();
	D3D->SpriteBegin();
	
	cout << "Game.cpp CurStateRender: 185";
	if(CurState)
		CurState->Render();

	// End D3D Rendering
	D3D->SpriteEnd();
	D3D->DeviceEnd();

	// Present
	D3D->Present();
}

// Cleanup
void Game::Shutdown( void )
{
	if(this->blankRectBmpID != -1)
	{
		TM->UnloadTexture(this->blankRectBmpID);
		this->blankRectBmpID = -1;
	}

	// Shutdown the SGD Wrappers in the opposite order of initialization
	if(CurState != nullptr)
	{
		CurState->Exit();
	}

	if(Manager != nullptr)
	{
		Manager->DeleteInstance();
		Manager = nullptr;
	}

	if(XA != nullptr)
	{
		XA->ShutdownXAudio2();
		XA = nullptr;
	}

	if(DI != nullptr)
	{
		DI->ShutdownDirectInput();
		DI = nullptr;
	}

	if(TM != nullptr)
	{
		TM->ShutdownTextureManager();
		TM = nullptr;
	}

	if(D3D != nullptr)
	{
		D3D->ShutdownDirect3D();
		D3D = nullptr;
	}

	DeleteInstance();
}

void Game::ChangeState(GameState* pNewState)
{
	if(CurState)
		CurState->Exit();

	CurState = pNewState;

	if(CurState)
		CurState->Enter();
}

bool Game::LoadSettings(const char* szFileName)
{
	// Create the TinyXML Document
	TiXmlDocument doc;

	// Attempt to load the document from the file
	if(doc.LoadFile(szFileName) == false)
		return false;

	// Access the root element in the document
	TiXmlElement* pRoot = doc.RootElement();
	if(pRoot == nullptr)
		return false;

	// Read in settings from XML file
	TiXmlElement* pSettings = pRoot->FirstChildElement( "settings" );
	if(pSettings != nullptr)
	{
		Settings info = { };

		if(pSettings->Attribute("SfxVol", &info.Sfx) != nullptr)
			SfxVol = (float)info.Sfx;

		if(pSettings->Attribute("BgmVol", &info.Bgm) != nullptr)
			BgmVol = (float)info.Bgm;

		if(pSettings->Attribute("Pan", &info.Pan) != nullptr)
			Pan = (float)info.Pan;

		if(pSettings->Attribute("Fullscreen", &info.Fullscreen) != nullptr)
		{
			if(info.Fullscreen == 1)
				Fullscreen = true;
			else if(info.Fullscreen == 0)
				Fullscreen = false;
		}
	}
	return true;
}